package com.matrix.order.infrastructure.message;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.matrix.api.order.dto.CreateOrderDTO;
import com.matrix.order.application.OrderAppService;
import com.matrix.order.domain.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author 有点甜
 * @since 2025/8/3
 */
@Slf4j
@Component
@RocketMQTransactionListener
@RequiredArgsConstructor
public class OrderTransactionListener implements RocketMQLocalTransactionListener {

    private final OrderAppService orderAppService;
    private final OrderRepository orderRepository;
    private final ObjectMapper objectMapper;

    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        if (!(arg instanceof Map) || !(msg.getPayload() instanceof Map)) {
            log.error("Invalid message format in executeLocalTransaction. Arg or Payload is not a Map. Arg: {}, Payload: {}", arg, msg.getPayload());
            return RocketMQLocalTransactionState.ROLLBACK;
        }
        @SuppressWarnings("unchecked")
        Map<String, Object> args = (Map<String, Object>) arg;

        String orderNo = (String) args.get("orderNo");
        Long userId = (Long) args.get("userId");

        @SuppressWarnings("unchecked")
        Map<String, Object> payload = (Map<String, Object>) msg.getPayload();

        CreateOrderDTO orderDTO = objectMapper.convertValue(payload.get("createOrderDTO"), CreateOrderDTO.class);

        log.info("开始执行下单本地事务, OrderNo: {}", orderNo);

        try {
            orderAppService.processOrderCreation(userId, orderDTO, orderNo);
            log.info("下单本地事务执行成功, 准备提交事务消息, OrderNo: {}", orderNo);
            return RocketMQLocalTransactionState.COMMIT;
        } catch (Exception e) {
            log.error("下单本地事务执行失败, 准备回滚事务消息, OrderNo: {}", orderNo, e);
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        if (!(msg.getPayload() instanceof Map)) {
            log.error("Invalid message format in checkLocalTransaction. Payload is not a Map. Payload: {}", msg.getPayload());
            return RocketMQLocalTransactionState.UNKNOWN;
        }

        @SuppressWarnings("unchecked")
        Map<String, Object> payload = (Map<String, Object>) msg.getPayload();
        String orderNo = (String) payload.get("orderNo");

        log.info("回查本地事务状态, OrderNo: {}", orderNo);

        boolean isSuccess = orderRepository.findByOrderNo(orderNo).isPresent();

        if (isSuccess) {
            log.info("回查结果: 本地事务成功, 提交事务消息, OrderNo: {}", orderNo);
            return RocketMQLocalTransactionState.COMMIT;
        } else {
            log.warn("回查结果: 本地事务未成功, 回滚事务消息, OrderNo: {}", orderNo);
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }
}